package com.heng.StampLockDemo;

import org.junit.Test;

import java.beans.Transient;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.StampedLock;

public class StampLockDemo2 {
    static int number = 37;
    static StampedLock stampedLock = new StampedLock();

    public void write() {
        long stamp = stampedLock.writeLock();
        System.out.println(Thread.currentThread().getName()+"\t写线程准备修改");
        try {
            number += 13;

        }finally {
            stampedLock.unlockWrite(stamp);
        }
        System.out.println(Thread.currentThread().getName()+"\t写线程结束修改");
    }


    //悲观读，读没有完成时写锁无法获得
    public void read(){
        long stamp = stampedLock.readLock();
        System.out.println(Thread.currentThread().getName()+"\t come in");
        for (int i = 0; i < 4; i++) {
            try{
                TimeUnit.SECONDS.sleep(1);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        try {
            int result = number;
            System.out.println(Thread.currentThread().getName()+"\tresult:"+result);
            System.out.println("写线程没有修改成功，读锁时 写锁无法介入");
        }finally {
            stampedLock.unlockRead(stamp);
        }
    }

    //乐观读，读的过程中也允许获取写锁介入
    public void tryOptimisticRead() {
        long stamp = stampedLock.tryOptimisticRead();
        int result = number;
        //故意间隔4秒钟，很乐观认为读取中没有其他线程修改过number值
        System.out.println("4秒前stampLock.validate方法值（true无修改,false有修改）\t"+stampedLock.validate(stamp));
        for(int i = 0;i<4 ;i++) {
            try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e) {e.printStackTrace();}

            System.out.println(Thread.currentThread().getName()+"\t正在读取中..."+i+"秒"+
                    "后stampLock.validate方法值（true无修改,false有修改）\t"+stampedLock.validate(stamp));
        }
        if(!stampedLock.validate(stamp)){
            System.out.println("有人修改过");
            stamp = stampedLock.readLock();
            try {
                System.out.println("从乐观读 升级为 悲观读");
                result = number;
                System.out.println("悲观读后result："+result);
            }finally {
                stampedLock.unlockRead(stamp);
            }
        }
        System.out.println(Thread.currentThread().getName()+"finally value:"+result);
    }

    public static void main(String[] args) {
        StampLockDemo2 resource = new StampLockDemo2();
        new Thread(()->{
            resource.read();
        },"readThread").start();

        try{
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            resource.write();
        },"writeThread").start();

        try{TimeUnit.SECONDS.sleep(5);}catch (InterruptedException e) {e.printStackTrace();}

        System.out.println(number);

    }
    @Test
    public void rw(){
        StampLockDemo2 resource = new StampLockDemo2();
        new Thread(()->{
            resource.tryOptimisticRead();
        },"readThread").start();

        try {TimeUnit.SECONDS.sleep(2);}catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"\t---come in");
            resource.write();
        },"writeThread").start();
    }
}
